#![cfg_attr(
all(not(debug_assertions), target_os = "windows"),
windows_subsystem = "windows"
)]
#![windows_subsystem = "windows"]
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use std::sync::Arc;

use druid::{AppDelegate, AppLauncher, Application, Command, Data, DelegateCtx, Env, Handled, LocalizedString, Target, Widget, WidgetExt, WindowDesc, WindowState, Screen};
use druid::commands::{CLOSE_WINDOW, SHOW_WINDOW};
use druid::widget::{Button, Checkbox, CrossAxisAlignment, Flex, TextBox};

use crate::controller::CloseController;
use crate::state::AppState;

mod controller;
mod state;

const WINDOW_TITLE: LocalizedString<AppState> =
    LocalizedString::new("MyBatis问号替换工具v0.9.2-beta.4");

const EXPLAINER: &str = r###"Preparing: with t as ( select id, warn_type_code, data_batch_time, max_grade from warn_event where (warn_type_code, data_batch_time) in ( select warn_type_code, max(data_batch_time) from warn_event t1 where t1.product_id = ? and t1.warn_type_code = ? group by warn_type_code ) ) select substr(t1.time,0,9) as "day", max(t1.max_grade) as "warnGrade" from t join warn_event_info t1 on t1.event_id = t.id join warn_weather_pre t2 on t2.warn_info_id = t1.id where t2.province_code = ? and t2.start_time >= ? and t2.end_time <= ? group by substr(t1.time,0,9)
19:04:20.476 [main] DEBUG com.powergrid.mapper.warning.WarnWeatherPointMapper.stats3dayWarnGradeGdfsWarning - ==> Parameters: gdfs_warning(String), warning_short_term_pre(String), 320000(String), 202106150000(String), 202106150000(String)"###;

const PREPARING: &str = "Preparing: ";
const PARAM: &str = "Parameters: ";

fn main() {
    //create the initial app state
    let initial_state = AppState {
        result: "".to_string().into(),
        sql: "".to_string().into(),
        param: "".to_string().into(),
        to_clipboard: true,
    };

    let point = Screen::get_display_rect().center();
    let mut origin_center = point.clone();
    origin_center.x = origin_center.x - 800.0 / 2.0;
    origin_center.y = origin_center.y - 600.0 / 2.0;
    let win = WindowDesc::new(build_root_widget())
        .title(WINDOW_TITLE)
        .set_position(origin_center)
        .set_window_state(WindowState::Restored)
        .window_size((800.0, 600.0));


    AppLauncher::with_window(win)
        .delegate(Delegate {})
        .log_to_console()
        .launch(initial_state)
        .expect("启动失败");
}

fn build_root_widget() -> impl Widget<AppState> {
    Flex::column()
        .cross_axis_alignment(CrossAxisAlignment::Center)
        .with_child(
            Flex::row()

                .with_flex_spacer(1.0)
                .with_child(Button::new("转换").on_click(|_, data: &mut AppState, _| {
                    if data.sql.trim().is_empty() {
                        let clipboard = Application::global().clipboard();
                        //    clipboard.put_string("watch it there pal");
                        if let Some(contents) = clipboard.get_string() {
                            let x1 = contents.as_str().trim().starts_with(PREPARING);
                            if x1 {
                                data.sql = Arc::from(String::from(contents.as_str()));
                            } else {
                                return;
                            }
                        }
                    }
                    let x = data.sql.clone();
                    let split = x.as_str().split("\n");
                    let content_vec: Vec<&str> = split.collect();

                    if content_vec.len() >= 2 {
                        let sql = content_vec[0];
                        let param = content_vec[1];
                        let param: Vec<&str> = param.split(PARAM).collect();
                        if param.len() < 2 {
                            return;
                        }
                        let param = param[1];
                        let params: Vec<&str> = param.split(")").collect();
                        let mut params2 = params.iter();
                        let mut sql_result = String::new();
                        let cc: Vec<char> = sql.replace(PREPARING, "").chars().collect();

                        for (_, x) in cc.iter().enumerate() {
                            if *x == '?' {
                                let s = params2.next().unwrap();
                                let val_type: Vec<&str> = s.split("(").collect();
                                if val_type[1].starts_with("String") {
                                    sql_result.push_str(
                                        format!("'{}'", val_type[0].trim_start_matches(',').trim_start()).as_str(),
                                    );
                                } else {
                                    sql_result.push_str(val_type[0].trim_start_matches(',').trim());
                                }
                            } else {
                                sql_result.push_str(String::from(*x).as_str());
                            }
                        }

                        data.result = Arc::from(String::from(sql_result));
                        data.param = Arc::from(String::from(param));

                        if data.to_clipboard {
                            crate::Application::global()
                                .clipboard()
                                .put_string(data.result.as_str());
                        }
                    } else {
                        println!("格式不对!");
                    }
                }))
                .with_flex_spacer(1.0)
                .with_child(Button::new("粘贴").on_click(|_, _data: &mut AppState, _| {
                    let clipboard = Application::global().clipboard();
                    //    clipboard.put_string("watch it there pal");
                    if let Some(contents) = clipboard.get_string() {
                        let x1 = contents.as_str().trim().starts_with(PREPARING);
                        if x1 ==true {
                            _data.sql = Arc::from(String::from(contents.as_str()));
                        }

                    }
                }))
                .with_flex_spacer(1.0)
                .with_child(Button::new("复制").on_click(|_, data: &mut AppState, _| {
                    crate::Application::global()
                        .clipboard()
                        .put_string(data.result.as_str());
                }))
                .with_flex_spacer(1.0)
                .with_child(Button::new("样例").on_click(|_, data: &mut AppState, _| {
                    data.sql = Arc::from(String::from(EXPLAINER));
                }))
                .with_flex_spacer(1.0)
                .with_child(Checkbox::new("使用剪切板").lens(AppState::to_clipboard)),
        )
        .with_default_spacer()
        .with_flex_child(
            Flex::row().with_flex_child(
                TextBox::multiline()
                    .with_line_wrapping(true)
                    .with_placeholder(
                        "Preparing: xxxxx\n[换行]\
                Parameters: xxxx\n 点击顶部实例，装填到文本框，查看效果",
                    )
                    .expand_width()
                    .expand_height()
                    .lens(AppState::sql),
                1.0,
            ),
            1.0,
        )
        .with_default_spacer()
        .with_flex_child(
            TextBox::multiline()
                .with_line_wrapping(true)
                .with_placeholder("result")
                .expand_width()
                .expand_height()
                .lens(AppState::result),
            1.0,
        )
        .padding(8.0)
        .controller(CloseController::new())
}

struct Delegate {
}

impl<T: Data> AppDelegate<T> for Delegate {
    fn command(
        &mut self,
        _ctx: &mut DelegateCtx,
        _target: Target,
        cmd: &Command,
        _data: &mut T,
        _env: &Env,
    ) -> Handled {
        match Some(_target) {
            _ if cmd.is(SHOW_WINDOW) => {
                println!("target=close");
                // _ctx.submit_command(CLOSE_WINDOW);
                Handled::Yes
            },
            _ if cmd.is(CLOSE_WINDOW) => {
                println!("target=quit");
                Application::global().quit();
                Handled::Yes
            },
            _ => {
                Handled::No
            }
        }
    }
}
